#pragma once

#define ZENO_PP_COMMA() ,
#define ZENO_PP_LEFT_BRACE() (
#define ZENO_PP_RIGHT_BRACE() )
#define ZENO_PP_EVAL_7(...) __VA_ARGS__
#define ZENO_PP_EVAL_6(...) ZENO_PP_EVAL_7(__VA_ARGS__)
#define ZENO_PP_EVAL_5(...) ZENO_PP_EVAL_6(__VA_ARGS__)
#define ZENO_PP_EVAL_4(...) ZENO_PP_EVAL_5(__VA_ARGS__)
#define ZENO_PP_EVAL_3(...) ZENO_PP_EVAL_4(__VA_ARGS__)
#define ZENO_PP_EVAL_2(...) ZENO_PP_EVAL_3(__VA_ARGS__)
#define ZENO_PP_EVAL_1(...) ZENO_PP_EVAL_2(__VA_ARGS__)
#define ZENO_PP_EVAL(...) ZENO_PP_EVAL_1(__VA_ARGS__)
#define ZENO_PP_CALL_7(f, ...) ZENO_PP_EVAL_7(f(__VA_ARGS__))
#define ZENO_PP_CALL_6(f, ...) ZENO_PP_CALL_7(f, __VA_ARGS__)
#define ZENO_PP_CALL_5(f, ...) ZENO_PP_CALL_6(f, __VA_ARGS__)
#define ZENO_PP_CALL_4(f, ...) ZENO_PP_CALL_5(f, __VA_ARGS__)
#define ZENO_PP_CALL_3(f, ...) ZENO_PP_CALL_4(f, __VA_ARGS__)
#define ZENO_PP_CALL_2(f, ...) ZENO_PP_CALL_3(f, __VA_ARGS__)
#define ZENO_PP_CALL_1(f, ...) ZENO_PP_CALL_2(f, __VA_ARGS__)
#define ZENO_PP_CALL(f, ...) ZENO_PP_CALL_1(f, __VA_ARGS__)
#define ZENO_PP_STR(...) #__VA_ARGS__
#define ZENO_PP_CONCAT_1(x, y) x##y
#define ZENO_PP_CONCAT(x, y) ZENO_PP_CALL(ZENO_PP_CONCAT_1, x, y)
#define ZENO_PP_COUNT_ARGS_1(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, ...) _16
#define ZENO_PP_COUNT_ARGS(...) ZENO_PP_EVAL(ZENO_PP_COUNT_ARGS_1(__VA_ARGS__ __VA_OPT__(,) 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
#define ZENO_PP_HAS_ARGS_1(_1, _2, ...) _2
#define ZENO_PP_HAS_ARGS(...) ZENO_PP_EVAL(ZENO_PP_HAS_ARGS_1(__VA_OPT__(,) 1, 0))
#define ZENO_PP_GET_NTH_0(x, ...) x
#define ZENO_PP_GET_NTH_1(x, ...) ZENO_PP_GET_NTH_0(__VA_ARGS__)
#define ZENO_PP_GET_NTH_2(x, ...) ZENO_PP_GET_NTH_1(__VA_ARGS__)
#define ZENO_PP_GET_NTH_3(x, ...) ZENO_PP_GET_NTH_2(__VA_ARGS__)
#define ZENO_PP_GET_NTH_4(x, ...) ZENO_PP_GET_NTH_3(__VA_ARGS__)
#define ZENO_PP_GET_NTH_5(x, ...) ZENO_PP_GET_NTH_4(__VA_ARGS__)
#define ZENO_PP_GET_NTH_6(x, ...) ZENO_PP_GET_NTH_5(__VA_ARGS__)
#define ZENO_PP_GET_NTH_7(x, ...) ZENO_PP_GET_NTH_6(__VA_ARGS__)
#define ZENO_PP_GET_NTH_8(x, ...) ZENO_PP_GET_NTH_7(__VA_ARGS__)
#define ZENO_PP_GET_NTH_9(x, ...) ZENO_PP_GET_NTH_8(__VA_ARGS__)
#define ZENO_PP_GET_NTH_10(x, ...) ZENO_PP_GET_NTH_9(__VA_ARGS__)
#define ZENO_PP_GET_NTH_11(x, ...) ZENO_PP_GET_NTH_10(__VA_ARGS__)
#define ZENO_PP_GET_NTH_12(x, ...) ZENO_PP_GET_NTH_11(__VA_ARGS__)
#define ZENO_PP_GET_NTH_13(x, ...) ZENO_PP_GET_NTH_12(__VA_ARGS__)
#define ZENO_PP_GET_NTH_14(x, ...) ZENO_PP_GET_NTH_13(__VA_ARGS__)
#define ZENO_PP_GET_NTH_15(x, ...) ZENO_PP_GET_NTH_14(__VA_ARGS__)
#define ZENO_PP_GET_NTH(...) ZENO_PP_CALL(ZENO_PP_CONCAT(ZENO_PP_GET_NTH_, ZENO_PP_COUNT_ARGS(__VA_ARGS__)) __VA_OPT__(,) __VA_ARGS__)
#define ZENO_PP_GET_INV_NTH_15(x, ...) x
#define ZENO_PP_GET_INV_NTH_14(x, ...) ZENO_PP_GET_INV_NTH_15(__VA_ARGS__)
#define ZENO_PP_GET_INV_NTH_13(x, ...) ZENO_PP_GET_INV_NTH_14(__VA_ARGS__)
#define ZENO_PP_GET_INV_NTH_12(x, ...) ZENO_PP_GET_INV_NTH_13(__VA_ARGS__)
#define ZENO_PP_GET_INV_NTH_11(x, ...) ZENO_PP_GET_INV_NTH_12(__VA_ARGS__)
#define ZENO_PP_GET_INV_NTH_10(x, ...) ZENO_PP_GET_INV_NTH_11(__VA_ARGS__)
#define ZENO_PP_GET_INV_NTH_9(x, ...) ZENO_PP_GET_INV_NTH_10(__VA_ARGS__)
#define ZENO_PP_GET_INV_NTH_8(x, ...) ZENO_PP_GET_INV_NTH_9(__VA_ARGS__)
#define ZENO_PP_GET_INV_NTH_7(x, ...) ZENO_PP_GET_INV_NTH_8(__VA_ARGS__)
#define ZENO_PP_GET_INV_NTH_6(x, ...) ZENO_PP_GET_INV_NTH_7(__VA_ARGS__)
#define ZENO_PP_GET_INV_NTH_5(x, ...) ZENO_PP_GET_INV_NTH_6(__VA_ARGS__)
#define ZENO_PP_GET_INV_NTH_4(x, ...) ZENO_PP_GET_INV_NTH_5(__VA_ARGS__)
#define ZENO_PP_GET_INV_NTH_3(x, ...) ZENO_PP_GET_INV_NTH_4(__VA_ARGS__)
#define ZENO_PP_GET_INV_NTH_2(x, ...) ZENO_PP_GET_INV_NTH_3(__VA_ARGS__)
#define ZENO_PP_GET_INV_NTH_1(x, ...) ZENO_PP_GET_INV_NTH_2(__VA_ARGS__)
#define ZENO_PP_GET_INV_NTH_0(x, ...) ZENO_PP_GET_INV_NTH_1(__VA_ARGS__)
#define ZENO_PP_GET_INV_NTH(...) ZENO_PP_CALL(ZENO_PP_CONCAT(ZENO_PP_GET_INV_NTH_, ZENO_PP_COUNT_ARGS(__VA_ARGS__)) __VA_OPT__(,) __VA_ARGS__)
#define ZENO_PP_FOREACH_0(f)
#define ZENO_PP_FOREACH_1(f, x) f(x)
#define ZENO_PP_FOREACH_2(f, x, y) f(x) f(y)
#define ZENO_PP_FOREACH_3(f, x, y, z) f(x) f(y) f(z)
#define ZENO_PP_FOREACH_4(f, x, y, z, w) f(x) f(y) f(z) f(w)
#define ZENO_PP_FOREACH_5(f, x, ...) f(x) ZENO_PP_FOREACH_4(__VA_ARGS__)
#define ZENO_PP_FOREACH_6(f, x, ...) f(x) ZENO_PP_FOREACH_5(__VA_ARGS__)
#define ZENO_PP_FOREACH_7(f, x, ...) f(x) ZENO_PP_FOREACH_6(__VA_ARGS__)
#define ZENO_PP_FOREACH_8(f, x, ...) f(x) ZENO_PP_FOREACH_7(__VA_ARGS__)
#define ZENO_PP_FOREACH_9(f, x, ...) f(x) ZENO_PP_FOREACH_8(__VA_ARGS__)
#define ZENO_PP_FOREACH_10(f, x, ...) f(x) ZENO_PP_FOREACH_9(__VA_ARGS__)
#define ZENO_PP_FOREACH_11(f, x, ...) f(x) ZENO_PP_FOREACH_10(__VA_ARGS__)
#define ZENO_PP_FOREACH_12(f, x, ...) f(x) ZENO_PP_FOREACH_11(__VA_ARGS__)
#define ZENO_PP_FOREACH_13(f, x, ...) f(x) ZENO_PP_FOREACH_12(__VA_ARGS__)
#define ZENO_PP_FOREACH_14(f, x, ...) f(x) ZENO_PP_FOREACH_13(__VA_ARGS__)
#define ZENO_PP_FOREACH_15(f, x, ...) f(x) ZENO_PP_FOREACH_14(__VA_ARGS__)
#define ZENO_PP_FOREACH(...) ZENO_PP_CALL(ZENO_PP_CONCAT(ZENO_PP_FOREACH_, ZENO_PP_COUNT_ARGS(__VA_ARGS__)) __VA_OPT__(,) __VA_ARGS__)
#define ZENO_PP_REPEAT_0(x)
#define ZENO_PP_REPEAT_1(x) x()
#define ZENO_PP_REPEAT_2(x) x() x()
#define ZENO_PP_REPEAT_3(x) x() x() x()
#define ZENO_PP_REPEAT_4(x) x() x() x() x()
#define ZENO_PP_REPEAT_5(x) x() ZENO_PP_REPEAT_4(x)
#define ZENO_PP_REPEAT_6(x) x() ZENO_PP_REPEAT_5(x)
#define ZENO_PP_REPEAT_7(x) x() ZENO_PP_REPEAT_6(x)
#define ZENO_PP_REPEAT_8(x) x() ZENO_PP_REPEAT_7(x)
#define ZENO_PP_REPEAT_9(x) x() ZENO_PP_REPEAT_8(x)
#define ZENO_PP_REPEAT_10(x) x() ZENO_PP_REPEAT_9(x)
#define ZENO_PP_REPEAT_11(x) x() ZENO_PP_REPEAT_10(x)
#define ZENO_PP_REPEAT_12(x) x() ZENO_PP_REPEAT_11(x)
#define ZENO_PP_REPEAT_13(x) x() ZENO_PP_REPEAT_12(x)
#define ZENO_PP_REPEAT_14(x) x() ZENO_PP_REPEAT_13(x)
#define ZENO_PP_REPEAT_15(x) x() ZENO_PP_REPEAT_14(x)
#define ZENO_PP_REPEAT(...) ZENO_PP_CALL(ZENO_PP_CONCAT(ZENO_PP_REPEAT_, ZENO_PP_COUNT_ARGS(__VA_ARGS__)) __VA_OPT__(,) __VA_ARGS__)
#define ZENO_PP_IF_0(cond, t, ...) __VA_ARGS__
#define ZENO_PP_IF_1(cond, t, ...) t
#define ZENO_PP_IF(cond, ...) ZENO_PP_CALL(ZENO_PP_CONCAT(ZENO_PP_IF_, cond) __VA_OPT__(,) __VA_ARGS__)
#define ZENO_PP_IF_NOT_0(cond, t, ...) t
#define ZENO_PP_IF_NOT_1(cond, t, ...) __VA_ARGS__
#define ZENO_PP_IF_NOT(cond, ...) ZENO_PP_CALL(ZENO_PP_CONCAT(ZENO_PP_IF_NOT_, cond) __VA_OPT__(,) __VA_ARGS__)
#define ZENO_PP_ADD_1(x, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, ...) ZENO_PP_GET_INV_NTH(x, __VA_ARGS__)
#define ZENO_PP_ADD(x, y) ZENO_PP_CALL(ZENO_PP_ADD_1, x, ZENO_PP_REPEAT(y, ZENO_PP_COMMA) 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32)
